﻿/// <reference path="~/Scripts/FlowBasis/FlowBasis-all-vsdoc.js" />

FlowBasis.defineNamespace("Data");


FlowBasis.Data.ResultSetList = function (options) {
    var self = this;

    this.element = jQuery(options.container);

    this._afterResultSetLoadHandler = function () {
        self._afterResultSetLoad();
    };

    this._afterQueryUpdatedHandler = function () {
        self._loadMoreDataIfPossible();
    }; 

    if (options.itemConverter) {
        this.itemConverter = options.itemConverter;
    }
    else {
        this.itemConverter = function (item) {
            if (item.html) {
                return jQuery("<li>").html(item.html);
            }
            else if (item.text) {
                return jQuery("<li>").text(item.text);
            }
        }
    }

    if (options.listCssClass) {
        this.listCssClass = options.listCssClass;
    }
    else {
        this.listCssClass = null;
    }

    if (options.paging) {
        this.paging = options.paging;       
    }
    
    this._resetCurrentPage();

    this._shouldRenderAfterResultSetLoad = false;

    if (options.resultSet) {
        this.setResultSet(options.resultSet);        
    }
    else {
        this.resultSet = null;
    }
};


FlowBasis.Data.ResultSetList.prototype.setResultSet = function (newResultSet) {
    var self = this;

    if (this.resultSet) {
        jQuery(this.resultSet).unbind("afterResultSetLoad", this._afterResultSetLoadHandler);
        jQuery(this.resultSet).unbind("queryUpdated", this._afterQueryUpdatedHandler);
    }

    this._resetCurrentPage();
    this.resultSet = newResultSet;

    if (this.resultSet) {
        jQuery(this.resultSet).bind("afterResultSetLoad", this._afterResultSetLoadHandler);
        jQuery(this.resultSet).bind("queryUpdated", this._afterQueryUpdatedHandler);
    }

    if (this.resultSet.getCount() > 0) {
        // This is either a local result set or a remote result set for which we have loaded some data.
        this.render();
    }
    else {
        this._loadMoreDataIfPossible();
    }
};


FlowBasis.Data.ResultSetList.prototype._loadMoreDataIfPossible = function () {
    if (this.resultSet.canLoadMoreData && this.resultSet.canLoadMoreData()) {
        this._shouldRenderAfterResultSetLoad = true;
        this.resultSet.loadMoreData();
    }
};


FlowBasis.Data.ResultSetList.prototype._resetCurrentPage = function () {
    if (this.paging) {        
        if (!this.paging.resultsPerPage) {
            this.paging.resultsPerPage = 10;
        }

        this.currentPage = {
            firstIndex: 0,
            maxResults: this.paging.resultsPerPage
        };
    }
    else {
        this.currentPage = null;
    }
};


FlowBasis.Data.ResultSetList.prototype._afterResultSetLoad = function () { 
    if (this._shouldRenderAfterResultSetLoad) {
        this.render();
        this._shouldRenderAfterResultSetLoad = false;
    }
};


FlowBasis.Data.ResultSetList.prototype.render = function () {
    var self = this;

    jQuery(document).ready(function() {
        self.element.html("");

        if (!self.resultSet) {
            return null;
        }
        
        if (self.resultSet.hasError && self.resultSet.hasError()) {
            var error = self.resultSet.getError();
            var errorDiv = jQuery("<div>").text(error.message);
            self.element.append(errorDiv);
            self.currentPage = null;
        }
        else {
            var list = jQuery("<ul>");

            if (self.listCssClass) {
                list.addClass(self.listCssClass);
            }

            var offset;
            var count;

            if (self.paging) {
                var lastLoadedIndexPlus1 = self.resultSet.getOffset() + self.resultSet.getCount();

                offset = self.currentPage.firstIndex;
                count = self.currentPage.maxResults;

                if (offset + count > lastLoadedIndexPlus1) {
                    count = lastLoadedIndexPlus1 - offset;
                }
            }
            else {
                offset = self.resultSet.getOffset();
                count = self.resultSet.getCount();
            }    

            for (var i = 0; i < count; i++) {
                var index = offset + i;
                var item = self.resultSet.getEntry(index);

                if (item) {
                    var listItem = self.itemConverter(item);
                    list.append(listItem);
                }
            }

            if (self.currentPage) {
                self.currentPage.count = count;
            }

            self.element.append(list);
        }

        jQuery(self).trigger("afterRender");
    });
};


FlowBasis.Data.ResultSetList.prototype.setPageFirstIndex = function (newFirstIndex) {
    this.currentPage = {};
    this.currentPage.firstIndex = newFirstIndex;
    this.currentPage.maxResults = this.paging.resultsPerPage;

    var pageOffset = this.currentPage.firstIndex;
    var pageEnd = pageOffset + this.currentPage.maxResults;

    var resultSetOffset = this.resultSet.getOffset();
    var resultSetCount = this.resultSet.getCount();
    var resultSetEnd = resultSetOffset + resultSetCount;

    if (resultSetOffset <= pageOffset && resultSetEnd >= pageEnd) {
        // We have all the data we need, so just render the result set.
        this.render();
    }
    else {
        if (this.resultSet.canLoadMoreData && this.resultSet.canLoadMoreData()) {
            this._shouldRenderAfterResultSetLoad = true;
            this.resultSet.loadMoreData(pageOffset);
        }
        else {
            // We cannot load any more data, so use what we have.
            this.render();
        }
    }
};


FlowBasis.Data.ResultSetList.prototype.gotoPreviousPage = function () {
    if (this.currentPage) {
        var newFirstIndex = Math.max(this.currentPage.firstIndex - this.paging.resultsPerPage, 0);
        this.setPageFirstIndex(newFirstIndex);
    }
};

FlowBasis.Data.ResultSetList.prototype.gotoNextPage = function () {
    if (this.hasNextPage()) {
        this.setPageFirstIndex(this.currentPage.firstIndex + this.currentPage.count);
    }
};

FlowBasis.Data.ResultSetList.prototype.hasPreviousPage = function () {
    if (this.currentPage && this.currentPage.firstIndex > 0) {
        return true;
    }
    else {
        return false;
    }
};

FlowBasis.Data.ResultSetList.prototype.hasNextPage = function () {
    if (this.currentPage) {
        var pageOffset = this.currentPage.firstIndex;
        var pageEnd = pageOffset + this.currentPage.count;

        var overallCount = this.resultSet.getOverallCount();
        if (overallCount === null) {
            // See if we are at end of currently loaded data.
            var resultSetOffset = this.resultSet.getOffset();
            var resultSetEnd = resultSetOffset + this.resultSet.getCount();

            if (pageEnd < resultSetEnd) {
                return true;
            }
            else {
                if (this.resultSet.canLoadMoreData && this.resultSet.canLoadMoreData()) {
                    return true;
                }
                else {
                    return false;
                }
            }
        }
        else {
            if (pageEnd < overallCount) {
                return true;
            }
            else {
                return false;
            }
        }
    }
    else {
        return false;
    }
};

FlowBasis.Data.ResultSetList.prototype.getCurrentPageInfo = function () {
    if (this.currentPage) {
        var currentPageInfo = {};
        currentPageInfo.firstIndex = this.currentPage.firstIndex;
        currentPageInfo.count = this.currentPage.count;

        currentPageInfo.pageIndex = Math.floor(this.currentPage.firstIndex / this.paging.resultsPerPage);

        var overallCount = this.resultSet.getOverallCount();
        if (overallCount !== null) {
            currentPageInfo.overallResultCount = overallCount;
            currentPageInfo.pageCount = Math.ceil(overallCount / this.paging.resultsPerPage);
        }

        return currentPageInfo;
    }
    else {
        return null;
    }
};

FlowBasis.Data.ResultSetList.prototype.gotoPageIndex = function (pageIndex) {
    if (this.currentPage) {
        this.setPageFirstIndex(pageIndex * this.paging.resultsPerPage);
    }
};